package com.ruoyi.system.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 字段变更对比工具类（用于获取增删改操作的字段前后值）
 */
public class FieldChangeUtils {

    /**
     * 对比两个对象的字段差异（适用于update操作）
     */
    public static List<FieldDiff> compare(Object oldObj, Object newObj) {
        List<FieldDiff> diffs = new ArrayList<>();
        if (oldObj == null || newObj == null || !oldObj.getClass().equals(newObj.getClass())) {
            return diffs;
        }

        // 获取所有字段（包括父类字段）
        List<Field> fields = getAllFields(oldObj.getClass());
        
        for (Field field : fields) {
            // 跳过序列化相关字段和静态字段
            if (field.getName().equals("serialVersionUID") || java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            try {
                // 获取字段的getter方法
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), oldObj.getClass());
                Method readMethod = pd.getReadMethod();
                if (readMethod == null) continue;

                // 读取字段值
                Object oldVal = readMethod.invoke(oldObj);
                Object newVal = readMethod.invoke(newObj);

                // 字段值有变化
                if (!equals(oldVal, newVal)) {
                    FieldDiff diff = new FieldDiff();
                    diff.setFieldName(field.getName());
                    diff.setOldValue(formatValue(oldVal));
                    diff.setNewValue(formatValue(newVal));
                    diffs.add(diff);
                }
            } catch (Exception e) {
                // 忽略反射异常
            }
        }
        return diffs;
    }

    /**
     * 获取新增对象的所有字段（适用于insert操作）
     */
    public static List<FieldDiff> getInsertFields(Object obj) {
        List<FieldDiff> diffs = new ArrayList<>();
        if (obj == null) return diffs;

        List<Field> fields = getAllFields(obj.getClass());
        for (Field field : fields) {
            if (field.getName().equals("serialVersionUID") || java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            try {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
                Method readMethod = pd.getReadMethod();
                if (readMethod == null) continue;

                Object value = readMethod.invoke(obj);
                FieldDiff diff = new FieldDiff();
                diff.setFieldName(field.getName());
                diff.setNewValue(formatValue(value));
                diffs.add(diff);
            } catch (Exception e) {
                // 忽略异常
            }
        }
        return diffs;
    }

    /**
     * 获取删除对象的所有字段（适用于delete操作）
     */
    public static List<FieldDiff> getDeleteFields(Object obj) {
        List<FieldDiff> diffs = new ArrayList<>();
        if (obj == null) return diffs;

        List<Field> fields = getAllFields(obj.getClass());
        for (Field field : fields) {
            if (field.getName().equals("serialVersionUID") || java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            try {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
                Method readMethod = pd.getReadMethod();
                if (readMethod == null) continue;

                Object value = readMethod.invoke(obj);
                FieldDiff diff = new FieldDiff();
                diff.setFieldName(field.getName());
                diff.setOldValue(formatValue(value));
                diffs.add(diff);
            } catch (Exception e) {
                // 忽略异常
            }
        }
        return diffs;
    }

    /**
     * 获取类的所有字段（包括父类）
     */
    private static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                fields.add(field);
            }
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

    /**
     * 格式化字段值（处理特殊类型）
     */
    private static String formatValue(Object value) {
        if (value == null) return null;
        // 处理日期类型
        if (value instanceof java.util.Date) {
            return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.util.Date) value);
        }
        // 处理集合类型
        if (value instanceof java.util.Collection) {
            return ((java.util.Collection<?>) value).size() + "个元素";
        }
        return value.toString();
    }

    /**
     * 比较两个对象是否相等
     */
    private static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

    /**
     * 字段差异模型
     */
    public static class FieldDiff {
        private String fieldName;
        private String oldValue;
        private String newValue;

        // getter和setter
        public String getFieldName() { return fieldName; }
        public void setFieldName(String fieldName) { this.fieldName = fieldName; }
        public String getOldValue() { return oldValue; }
        public void setOldValue(String oldValue) { this.oldValue = oldValue; }
        public String getNewValue() { return newValue; }
        public void setNewValue(String newValue) { this.newValue = newValue; }
    }
}
    